package com.roncoo.education.course.service.api.biz;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.validation.constraints.NotNull;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

import com.roncoo.education.common.core.base.Page;
import com.roncoo.education.common.core.base.Result;
import com.roncoo.education.common.core.enums.PostTypeEnum;
import com.roncoo.education.common.core.enums.StatusIdEnum;
import com.roncoo.education.common.core.enums.ZoneTypeIdEnum;
import com.roncoo.education.common.core.tools.BeanUtil;
import com.roncoo.education.common.core.tools.DateUtil;
import com.roncoo.education.course.dao.CourseDao;
import com.roncoo.education.course.dao.ExperimentDao;
import com.roncoo.education.course.dao.PostDao;
import com.roncoo.education.course.dao.SphereDao;
import com.roncoo.education.course.dao.ZoneCourseDao;
import com.roncoo.education.course.dao.ZoneDao;
import com.roncoo.education.course.dao.ZoneExperimentDao;
import com.roncoo.education.course.dao.ZoneSphereDao;
import com.roncoo.education.course.dao.impl.mapper.entity.Course;
import com.roncoo.education.course.dao.impl.mapper.entity.CourseExample;
import com.roncoo.education.course.dao.impl.mapper.entity.Experiment;
import com.roncoo.education.course.dao.impl.mapper.entity.ExperimentExample;
import com.roncoo.education.course.dao.impl.mapper.entity.Post;
import com.roncoo.education.course.dao.impl.mapper.entity.PostExample;
import com.roncoo.education.course.dao.impl.mapper.entity.Sphere;
import com.roncoo.education.course.dao.impl.mapper.entity.SphereExample;
import com.roncoo.education.course.dao.impl.mapper.entity.Zone;
import com.roncoo.education.course.dao.impl.mapper.entity.ZoneCourse;
import com.roncoo.education.course.dao.impl.mapper.entity.ZoneCourseExample;
import com.roncoo.education.course.dao.impl.mapper.entity.ZoneExample;
import com.roncoo.education.course.dao.impl.mapper.entity.ZoneExperiment;
import com.roncoo.education.course.dao.impl.mapper.entity.ZoneExperimentExample;
import com.roncoo.education.course.dao.impl.mapper.entity.ZoneSphere;
import com.roncoo.education.course.dao.impl.mapper.entity.ZoneSphereExample;
import com.roncoo.education.course.service.api.resp.ApiPostPageResp;
import com.roncoo.education.course.service.api.resp.ApiZoneCourseResp;
import com.roncoo.education.course.service.api.resp.ApiZoneExperimentResp;
import com.roncoo.education.course.service.api.resp.ApiZoneResp;
import com.roncoo.education.course.service.api.resp.ApiZoneSphereResp;
import com.roncoo.education.user.feign.interfaces.IFeignLecturer;
import com.roncoo.education.user.feign.interfaces.vo.LecturerViewVO;

import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor;

/**
 * @author fengyw
 */
@Component
@CacheConfig(cacheNames = {"course"})
@RequiredArgsConstructor
public class ApiZoneBiz {

	@Autowired
    private ZoneDao zoneDao;
	@Autowired
    private ZoneCourseDao zoneCourseDao;
	@Autowired
    private ZoneExperimentDao zoneExperimentDao;
	@Autowired
    private ZoneSphereDao zoneSphereDao;    
    @Autowired
    private CourseDao courseDao;
    @Autowired
    private ExperimentDao experimentDao;
    @Autowired
    private SphereDao sphereDao;
    @Autowired
    private PostDao postDao;
    @Autowired
    private ApiOptionsBiz optionsBiz;
    @NotNull
    private final IFeignLecturer feignLecturer;

    @Cacheable
    public Result<List<ApiZoneResp>> list() {
        // 获取所有可用专区
        ZoneExample example = new ZoneExample();
        example.createCriteria().andStatusIdEqualTo(StatusIdEnum.YES.getCode());
        example.setOrderByClause("sort asc, id desc");
        List<Zone> zoneList = zoneDao.listByExample(example);
        List<ApiZoneResp> result = BeanUtil.copyProperties(zoneList, ApiZoneResp.class);
        if (CollUtil.isNotEmpty(result)) {
            for (ApiZoneResp resp : result) {
            	if (ZoneTypeIdEnum.COURSE.getCode().equalsIgnoreCase(resp.getType())) {            		
            		List<Long> ids = zoneCourse(resp.getId());
            		CourseExample ex = new CourseExample();
            		ex.createCriteria().andIdIn(ids).andStatusIdEqualTo(StatusIdEnum.YES.getCode());
            		ex.setOrderByClause("sort asc, id desc");
            		List<Course> list = courseDao.listByExample(ex);
            		if (list == null || list.size() == 0) continue;
            		
            		Map<Long, Course> mapObj = list.stream().collect(Collectors.toMap(Course::getId, item -> item));
            		List<Course> retList = new ArrayList<Course>();
            		for (Long id : ids) {
            			retList.add(mapObj.get(id));
					}
            		
            		resp.setCourseList(BeanUtil.copyProperties(retList, ApiZoneCourseResp.class));            		
                    List<Long> lecturerIdList = retList.stream().map(Course::getLecturerId).collect(Collectors.toList());
                    Map<Long, LecturerViewVO> lecturerNameMap = feignLecturer.listByIds2(lecturerIdList);
            		for (ApiZoneCourseResp rsp : resp.getCourseList()) {
            			LecturerViewVO lecturer = lecturerNameMap.get(rsp.getLecturerId());
            			if (lecturer != null) {            				
            				rsp.setLecturerName(lecturer.getLecturerName());
            				rsp.setLecturerSchool(lecturer.getLecturerSchool());
            			}
					}
            	}
            	if (ZoneTypeIdEnum.EXPERIMENT.getCode().equalsIgnoreCase(resp.getType())) {            		
            		List<Long> ids = zoneExperiment(resp.getId());
            		ExperimentExample ex = new ExperimentExample();
            		ex.createCriteria().andIdIn(ids).andStatusIdEqualTo(StatusIdEnum.YES.getCode());
            		ex.setOrderByClause("sort asc, id desc");
            		List<Experiment> list = experimentDao.listByExample(ex);
            		if (list == null || list.size() == 0) continue;
            		list = optionsBiz.setOptionNameByOptionValue(list);

            		Map<Long, Experiment> mapObj = list.stream().collect(Collectors.toMap(Experiment::getId, item -> item));
            		List<Experiment> retList = new ArrayList<Experiment>();
            		for (Long id : ids) {
            			retList.add(mapObj.get(id));
					}
            		
            		resp.setExperimentList(BeanUtil.copyProperties(retList, ApiZoneExperimentResp.class));            		
                    List<Long> lecturerIdList = retList.stream().map(Experiment::getZuozheId).collect(Collectors.toList());
                    Map<Long, LecturerViewVO> lecturerNameMap = feignLecturer.listByIds2(lecturerIdList);
            		for (ApiZoneExperimentResp rsp : resp.getExperimentList()) {
            			LecturerViewVO lecturer = lecturerNameMap.get(rsp.getZuozheId());
            			if (lecturer != null) {            				
            				rsp.setLecturerName(lecturer.getLecturerName());
            				rsp.setLecturerSchool(lecturer.getLecturerSchool());
            			}
					}
            	}
            	if (ZoneTypeIdEnum.SPHERE.getCode().equalsIgnoreCase(resp.getType())) {            		
            		List<Long> ids = zoneSphere(resp.getId());
            		SphereExample ex = new SphereExample();
            		ex.createCriteria().andIdIn(ids).andStatusIdEqualTo(StatusIdEnum.YES.getCode());
            		ex.setOrderByClause("sort asc, id desc");
            		List<Sphere> list = sphereDao.listByExample(ex);
            		if (list == null || list.size() == 0) continue;

            		Map<Long, Sphere> mapObj = list.stream().collect(Collectors.toMap(Sphere::getId, item -> item));
            		List<Sphere> retList = new ArrayList<Sphere>();
            		for (Long id : ids) {
            			retList.add(mapObj.get(id));
					}
            		
            		resp.setSphereList(BeanUtil.copyProperties(retList, ApiZoneSphereResp.class));
            	}
            }
        }
        
        return Result.success(result);
    }    
    
    @Cacheable
    public Result<ApiZoneResp> listGonggao() {
        // 获取公告专区
        return Result.success(getPostZone(PostTypeEnum.GONGGAO));
    }
    
    @Cacheable
    public Result<ApiZoneResp> listZixun() {
        // 获取资讯专区
        return Result.success(getPostZone(PostTypeEnum.ZIXUN));
    }
    
    private ApiZoneResp getPostZone(PostTypeEnum postTypeEnum) {    	
        PostExample example = new PostExample();
        example.createCriteria().andStatusIdEqualTo(StatusIdEnum.YES.getCode()).andLeixingEqualTo(postTypeEnum.getCode());
        example.setOrderByClause("sort asc, id desc");
        Page<Post> pageList = postDao.page(0, 5, example);
        List<ApiPostPageResp> postList = new ArrayList<ApiPostPageResp>();
        
        for (Post post : pageList.getList()) {
        	ApiPostPageResp postResp = BeanUtil.copyProperties(post, ApiPostPageResp.class);
        	postResp.setGmtCreate(DateUtil.fromLocalDateTime(post.getGmtCreate()));
        	postResp.setGmtModified(DateUtil.fromLocalDateTime(post.getGmtModified()));
        	postList.add(postResp);
		}

//        List<ApiPostPageResp> postList = BeanUtil.copyProperties(pageList.getList(), ApiPostPageResp.class);
        
        ApiZoneResp zone = new ApiZoneResp();
        zone.setType(postTypeEnum.getCode());
        zone.setZoneName(postTypeEnum.getDesc());
        zone.setPostList(postList);
        
        return zone;
    }

    private List<Long> zoneCourse(Long zoneId) {
        ZoneCourseExample example = new ZoneCourseExample();
        example.createCriteria().andZoneIdEqualTo(zoneId);
        example.setOrderByClause("sort asc, id desc");
        List<ZoneCourse> result = zoneCourseDao.listByExample(example);
        return result.stream().map(ZoneCourse::getCourseId).collect(Collectors.toList());
    }
    
    private List<Long> zoneExperiment(Long zoneId) {
        ZoneExperimentExample example = new ZoneExperimentExample();
        example.createCriteria().andZoneIdEqualTo(zoneId);
        example.setOrderByClause("sort asc, id desc");
        List<ZoneExperiment> result = zoneExperimentDao.listByExample(example);
        return result.stream().map(ZoneExperiment::getExperimentId).collect(Collectors.toList());
    }
    
    private List<Long> zoneSphere(Long zoneId) {
        ZoneSphereExample example = new ZoneSphereExample();
        example.createCriteria().andZoneIdEqualTo(zoneId);
        example.setOrderByClause("sort asc, id desc");
        List<ZoneSphere> result = zoneSphereDao.listByExample(example);
        return result.stream().map(ZoneSphere::getSphereId).collect(Collectors.toList());
    }    
}
